home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 026-050 / 042 / mg1a / random.c < prev    next >
C/C++ Source or Header  |  1995-03-13  |  13KB  |  512 lines

  1. /*
  2.  *        Assorted commands.
  3.  * The file contains the command
  4.  * processors for a large assortment of unrelated
  5.  * commands. The only thing they have in common is
  6.  * that they are all command processors.
  7.  */
  8. #include    "def.h"
  9.  
  10. /*
  11.  * Display a bunch of useful information about
  12.  * the current location of dot. The character under the
  13.  * cursor (in octal), the current line, row, and column, and
  14.  * approximate position of the cursor in the file (as a percentage)
  15.  * is displayed. The column position assumes an infinite position
  16.  * display; it does not truncate just because the screen does.
  17.  * This is normally bound to "C-X =".
  18.  */
  19. /*ARGSUSED*/
  20. showcpos(f, n, k) {
  21.     register LINE    *clp;
  22.     register long    nchar;
  23.     long        cchar;
  24.     register int    nline, row;
  25.     int        cline, cbyte;    /* Current line/char/byte */
  26.     int        ratio;
  27.     KEY        keychar();
  28.  
  29.     clp = lforw(curbp->b_linep);        /* Collect the data.    */
  30.     nchar = 0;
  31.     nline = 0;
  32.     for (;;) {
  33.         ++nline;            /* Count this line    */
  34.         if (clp == curwp->w_dotp) {
  35.             cline = nline;        /* Mark line        */
  36.             cchar = nchar + curwp->w_doto;
  37.             if (curwp->w_doto == llength(clp))
  38.                 cbyte = '\n';
  39.             else
  40.                 cbyte = lgetc(clp, curwp->w_doto);
  41.         }
  42.         nchar += llength(clp) + 1;    /* Now count the chars    */
  43.         if (clp == curbp->b_linep) break ;
  44.         clp = lforw(clp);
  45.     }
  46.     row = curwp->w_toprow;            /* Determine row.    */
  47.     clp = curwp->w_linep;
  48.     while (clp!=curbp->b_linep && clp!=curwp->w_dotp) {
  49.         ++row;
  50.         clp = lforw(clp);
  51.     }
  52.     ++row;                    /* Convert to origin 1.    */
  53.     /*NOSTRICT*/    
  54.     /* nchar can't be zero (because of the "bonus" \n at end of file) */
  55.     ratio = (100L*cchar) / nchar;
  56.     ewprintf("Char: %c (0%o)  point=%ld(%d%%)  line=%d  row=%d  col=%d",
  57.         (int) keychar(cbyte, FALSE), cbyte, cchar, ratio, cline, row,
  58.         getcolpos());
  59.     return (TRUE);
  60. }
  61.  
  62. getcolpos() {
  63.     register int    col, i, c;
  64.  
  65.     col = 0;                /* Determine column.    */
  66.     for (i=0; i<curwp->w_doto; ++i) {
  67.         c = lgetc(curwp->w_dotp, i);
  68.         if (c == '\t')
  69.             col |= 0x07;
  70.         else if (ISCTRL(c) != FALSE)
  71.             ++col;
  72.         ++col;
  73.     }
  74.     return col + 1;                /* Convert to origin 1.    */
  75. }
  76. /*
  77.  * Twiddle the two characters on either side of
  78.  * dot. If dot is at the end of the line twiddle the
  79.  * two characters before it. Return with an error if dot
  80.  * is at the beginning of line; it seems to be a bit
  81.  * pointless to make this work. This fixes up a very
  82.  * common typo with a single stroke. Normally bound
  83.  * to "C-T". This always works within a line, so
  84.  * "WFEDIT" is good enough.
  85.  */
  86. /*ARGSUSED*/
  87. twiddle(f, n, k) {
  88.     register LINE    *dotp;
  89.     register int    doto, odoto;
  90.     register int    cl;
  91.     register int    cr;
  92.  
  93.     dotp = curwp->w_dotp;
  94.     odoto = doto = curwp->w_doto;
  95.     if (doto==llength(dotp) && --doto<0)
  96.         return (FALSE);
  97.     cr = lgetc(dotp, doto);
  98.     if (--doto < 0)
  99.         return (FALSE);
  100.     cl = lgetc(dotp, doto);
  101.     lputc(dotp, doto+0, cr);
  102.     lputc(dotp, doto+1, cl);
  103.     if (odoto != llength(dotp)) ++(curwp->w_doto);
  104.     lchange(WFEDIT);
  105.     return (TRUE);
  106. }
  107.  
  108. /*
  109.  * Quote the next character, and
  110.  * insert it into the buffer. All the characters
  111.  * are taken literally, with the exception of the newline,
  112.  * which always has its line splitting meaning. The character
  113.  * is always read, even if it is inserted 0 times, for
  114.  * regularity.
  115.  */
  116. /*ARGSUSED*/
  117. quote(f, n, k) {
  118.     register int    s;
  119.     register KEY    c;
  120.  
  121.     if (kbdmop != NULL) c = (KEY) *kbdmop++;
  122.     else c = getkey(KQUOTE);
  123.     if (n < 0)
  124.         return (FALSE);
  125.     if (n == 0)
  126.         return (TRUE);
  127.     if (c == '\n') {
  128.         do {
  129.             s = lnewline();
  130.         } while (s==TRUE && --n);
  131.         return (s);
  132.     }
  133.     return (linsert((RSIZE) n, (char) c));
  134. }
  135.  
  136. /*
  137.  * Ordinary text characters are bound to this function,
  138.  * which inserts them into the buffer. Characters marked as control
  139.  * characters (using the CTRL flag) may be remapped to their ASCII
  140.  * equivalent. This makes TAB (C-I) work right, and also makes the
  141.  * world look reasonable if a control character is bound to this
  142.  * this routine by hand. Any META or CTLX flags on the character
  143.  * are discarded. This is the only routine that actually looks
  144.  * the the "k" argument.
  145.  */
  146. /*ARGSUSED*/
  147. selfinsert(f, n, k) {
  148.     register int    c;
  149.  
  150.     if (n < 0)
  151.         return (FALSE);
  152.     if (n == 0)
  153.         return (TRUE);
  154.     c = k & KCHAR;
  155.     if ((k&KCTRL)!=0 && c>='@' && c<='_')    /* ASCII-ify.        */
  156.         c -= '@';
  157.     return (linsert((RSIZE) n, c));
  158. }
  159.  
  160. /*
  161.  * Open up some blank space. The basic plan
  162.  * is to insert a bunch of newlines, and then back
  163.  * up over them. Everything is done by the subcommand
  164.  * procerssors. They even handle the looping. Normally
  165.  * this is bound to "C-O".
  166.  */
  167. /*ARGSUSED*/
  168. openline(f, n, k) {
  169.     register int    i;
  170.     register int    s;
  171.  
  172.     if (n < 0)
  173.         return (FALSE);
  174.     if (n == 0)
  175.         return (TRUE);
  176.     i = n;                    /* Insert newlines.    */
  177.     do {
  178.         s = lnewline();
  179.     } while (s==TRUE && --i);
  180.     if (s == TRUE)                /* Then back up overtop    */
  181.         s = backchar(f, n, KRANDOM);    /* of them all.        */
  182.     return (s);
  183. }
  184.  
  185. /*
  186.  * Insert a newline.
  187.  * If you are at the end of the line and the
  188.  * next line is a blank line, just move into the
  189.  * blank line. This makes "C-O" and "C-X C-O" work
  190.  * nicely, and reduces the ammount of screen
  191.  * update that has to be done. This would not be
  192.  * as critical if screen update were a lot
  193.  * more efficient.
  194.  */
  195. /*ARGSUSED*/
  196. newline(f, n, k) {
  197.     register LINE    *lp;
  198.     register int    s;
  199.  
  200.     if (n < 0)
  201.         return (FALSE);
  202.     while (n--) {
  203.         lp = curwp->w_dotp;
  204.         if (llength(lp) == curwp->w_doto
  205.         && lp != curbp->b_linep
  206.         && llength(lforw(lp)) == 0) {
  207.             if ((s=forwchar(FALSE, 1, KRANDOM)) != TRUE)
  208.                 return (s);
  209.         } else if ((s=lnewline()) != TRUE)
  210.             return (s);
  211.     }
  212.     return (TRUE);
  213. }
  214.  
  215. /*
  216.  * Delete blank lines around dot.
  217.  * What this command does depends if dot is
  218.  * sitting on a blank line. If dot is sitting on a
  219.  * blank line, this command deletes all the blank lines
  220.  * above and below the current line. If it is sitting
  221.  * on a non blank line then it deletes all of the
  222.  * blank lines after the line. Normally this command
  223.  * is bound to "C-X C-O". Any argument is ignored.
  224.  */
  225. /*ARGSUSED*/
  226. deblank(f, n, k) {
  227.     register LINE    *lp1;
  228.     register LINE    *lp2;
  229.     register RSIZE    nld;
  230.  
  231.     lp1 = curwp->w_dotp;
  232.     while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  233.         lp1 = lp2;
  234.     lp2 = lp1;
  235.     nld = (RSIZE) 0;
  236.     while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  237.         ++nld;
  238.     if (nld == 0)
  239.         return (TRUE);
  240.     curwp->w_dotp = lforw(lp1);
  241.     curwp->w_doto = 0;
  242.     return (ldelete((RSIZE)nld, KNONE));
  243. }
  244.  
  245. /*
  246.  * Delete any whitespace around dot, then insert a space.
  247.  */
  248. /*ARGSUSED*/
  249. delwhite(f, n, k) {
  250.     register int    col, c, s;
  251.  
  252.     col = curwp->w_doto;
  253.     while ((c = lgetc(curwp->w_dotp, col)) == ' ' || c == '\t')
  254.         ++col;
  255.     do
  256.         if ((s = backchar(FALSE, 1, KRANDOM)) == FALSE) break;
  257.     while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || c == '\t') ;
  258.  
  259.     if (s == TRUE) (VOID) forwchar(FALSE, 1, KRANDOM);
  260.     (VOID) ldelete((RSIZE)(col - curwp->w_doto), KNONE);
  261.     return linsert((RSIZE) 1, ' ');
  262. }
  263. /*
  264.  * Insert a newline, then enough
  265.  * tabs and spaces to duplicate the indentation
  266.  * of the previous line. Assumes tabs are every eight
  267.  * characters. Quite simple. Figure out the indentation
  268.  * of the current line. Insert a newline by calling
  269.  * the standard routine. Insert the indentation by
  270.  * inserting the right number of tabs and spaces.
  271.  * Return TRUE if all ok. Return FALSE if one
  272.  * of the subcomands failed. Normally bound
  273.  * to "C-J".
  274.  */
  275. /*ARGSUSED*/
  276. indent(f, n, k) {
  277.     register int    nicol;
  278.     register int    c;
  279.     register int    i;
  280.  
  281.     if (n < 0)
  282.         return (FALSE);
  283.     while (n--) {
  284.         nicol = 0;
  285.         for (i=0; i<llength(curwp->w_dotp); ++i) {
  286.             c = lgetc(curwp->w_dotp, i);
  287.             if (c!=' ' && c!='\t')
  288.                 break;
  289.             if (c == '\t')
  290.                 nicol |= 0x07;
  291.             ++nicol;
  292.         }
  293.         if (lnewline() == FALSE
  294.         || ((i=nicol/8)!=0 && linsert((RSIZE) i, '\t')==FALSE)
  295.         || ((i=nicol%8)!=0 && linsert((RSIZE) i,  ' ')==FALSE))
  296.             return (FALSE);
  297.     }
  298.     return (TRUE);
  299. }
  300.  
  301. /*
  302.  * Delete forward. This is real
  303.  * easy, because the basic delete routine does
  304.  * all of the work. Watches for negative arguments,
  305.  * and does the right thing. If any argument is
  306.  * present, it kills rather than deletes, to prevent
  307.  * loss of text if typed with a big argument.
  308.  * Normally bound to "C-D".
  309.  */
  310. /*ARGSUSED*/
  311. forwdel(f, n, k) {
  312.     if (n < 0)
  313.         return (backdel(f, -n, KRANDOM));
  314.     if (f != FALSE) {            /* Really a kill.    */
  315.         if ((lastflag&CFKILL) == 0)
  316.             kdelete();
  317.         thisflag |= CFKILL;
  318.     }
  319.     return (ldelete((RSIZE) n, f ? KFORW : KNONE));
  320. }
  321.  
  322. /*
  323.  * Delete backwards. This is quite easy too,
  324.  * because it's all done with other functions. Just
  325.  * move the cursor back, and delete forwards.
  326.  * Like delete forward, this actually does a kill
  327.  * if presented with an argument.
  328.  */
  329. /*ARGSUSED*/
  330. backdel(f, n, k) {
  331.     register int    s;
  332.  
  333.     if (n < 0)
  334.         return (forwdel(f, -n, KRANDOM));
  335.     if (f != FALSE) {            /* Really a kill.    */
  336.         if ((lastflag&CFKILL) == 0)
  337.             kdelete();
  338.         thisflag |= CFKILL;
  339.     }
  340.     if ((s=backchar(f, n, KRANDOM)) == TRUE)
  341.         s = ldelete((RSIZE) n, f ? KFORW : KNONE);
  342.     return (s);
  343. }
  344.  
  345. /*
  346.  * Kill line. If called without an argument,
  347.  * it kills from dot to the end of the line, unless it
  348.  * is at the end of the line, when it kills the newline.
  349.  * If called with an argument of 0, it kills from the
  350.  * start of the line to dot. If called with a positive
  351.  * argument, it kills from dot forward over that number
  352.  * of newlines. If called with a negative argument it
  353.  * kills any text before dot on the current line,
  354.  * then it kills back abs(arg) lines.
  355.  */
  356. /*ARGSUSED*/
  357. killline(f, n, k) {
  358.     register RSIZE    chunk;
  359.     register LINE    *nextp;
  360.     register int    i, c;
  361.  
  362.     if ((lastflag&CFKILL) == 0)        /* Clear kill buffer if    */
  363.         kdelete();            /* last wasn't a kill.    */
  364.     thisflag |= CFKILL;
  365.     if (f == FALSE) {
  366.         for (i = curwp->w_doto; i < llength(curwp->w_dotp); ++i)
  367.             if ((c = lgetc(curwp->w_dotp, i)) != ' ' && c != '\t')
  368.                 break;
  369.         if (i == llength(curwp->w_dotp))
  370.             chunk = llength(curwp->w_dotp)-curwp->w_doto + 1;
  371.         else {
  372.             chunk = llength(curwp->w_dotp)-curwp->w_doto;
  373.             if (chunk == 0)
  374.                 chunk = 1;
  375.         }
  376.     } else if (n > 0) {
  377.         chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
  378.         nextp = lforw(curwp->w_dotp);
  379.         i = n;
  380.         while (--i) {
  381.             if (nextp == curbp->b_linep)
  382.                 break;
  383.             chunk += llength(nextp)+1;
  384.             nextp = lforw(nextp);
  385.         }
  386.     } else {                /* n <= 0        */
  387.         chunk = curwp->w_doto;
  388.         curwp->w_doto = 0;
  389.         i = n;
  390.         while (i++) {
  391.             if (lback(curwp->w_dotp) == curbp->b_linep)
  392.                 break;
  393.             curwp->w_dotp = lback(curwp->w_dotp);
  394.             curwp->w_flag |= WFMOVE;
  395.             chunk += llength(curwp->w_dotp)+1;
  396.         }
  397.     }
  398.     /*
  399.      * KFORW here is a bug. Should be KBACK/KFORW, but we need to
  400.      * rewrite the ldelete code (later)?
  401.      */
  402.     return (ldelete(chunk,  KFORW));
  403. }
  404.  
  405. /*
  406.  * Yank text back from the kill buffer. This
  407.  * is really easy. All of the work is done by the
  408.  * standard insert routines. All you do is run the loop,
  409.  * and check for errors. The blank
  410.  * lines are inserted with a call to "newline"
  411.  * instead of a call to "lnewline" so that the magic
  412.  * stuff that happens when you type a carriage
  413.  * return also happens when a carriage return is
  414.  * yanked back from the kill buffer.
  415.  * An attempt has been made to fix the cosmetic bug
  416.  * associated with a yank when dot is on the top line of
  417.  * the window (nothing moves, because all of the new
  418.  * text landed off screen).
  419.  */
  420. /*ARGSUSED*/
  421. yank(f, n, k) {
  422.     register int    c;
  423.     register int    i;
  424.     register LINE    *lp;
  425.     register int    nline;
  426.  
  427.     if (n < 0)
  428.         return (FALSE);
  429.     nline = 0;                /* Newline counting.    */
  430.     while (n--) {
  431.         isetmark();            /* mark around last yank */
  432.         i = 0;
  433.         while ((c=kremove(i)) >= 0) {
  434.             if (c == '\n') {
  435.                 if (newline(FALSE, 1, KRANDOM) == FALSE)
  436.                     return (FALSE);
  437.                 ++nline;
  438.             } else {
  439.                 if (linsert((RSIZE) 1, c) == FALSE)
  440.                     return (FALSE);
  441.             }
  442.             ++i;
  443.         }
  444.     }
  445.     lp = curwp->w_linep;            /* Cosmetic adjustment    */
  446.     if (curwp->w_dotp == lp) {        /* if offscreen insert.    */
  447.         while (nline-- && lback(lp)!=curbp->b_linep)
  448.             lp = lback(lp);
  449.         curwp->w_linep = lp;        /* Adjust framing.    */
  450.         curwp->w_flag |= WFHARD;
  451.     }
  452.     return (TRUE);
  453. }
  454. /*
  455.  * Commands to toggle the four modes. Without an argument, sets the
  456.  * mode on, with an argument, sets the mode off.
  457.  */
  458. /*ARGSUSED*/
  459. bsmapmode(f, n, k) {
  460.  
  461.     if (f == FALSE) mode |= MBSMAP;
  462.     else mode &= ~MBSMAP;
  463.     upmodes((BUFFER *) NULL);
  464.     return TRUE;
  465. }
  466.  
  467. /*ARGSUSED*/
  468. flowmode(f, n, k) {
  469.     if (f == FALSE) mode |= MFLOW;
  470.     else mode &= ~MFLOW;
  471.     upmodes((BUFFER *) NULL);
  472.     return TRUE;
  473. }
  474.  
  475. /*ARGSUSED*/
  476. indentmode(f, n, k) {
  477.  
  478.     if (f == FALSE) {
  479.         mode |= MINDENT;
  480.         if ((binding[KCTRL|'M'] = symlookup("newline-and-indent"))
  481.             == NULL)
  482.             panic("no newline-and-indent in indentmode");
  483.         if ((binding[KCTRL|'J'] = symlookup("insert-newline")) == NULL)
  484.             panic("no insert-newline in indentmode");
  485.     } else {
  486.         mode &= ~MINDENT;
  487.         if ((binding[KCTRL|'M'] = symlookup("insert-newline")) == NULL)
  488.             panic("no insert-newline in indentmode");
  489.         if ((binding[KCTRL|'J'] = symlookup("newline-and-indent"))
  490.             == NULL)
  491.             panic("no newline-and-indent in indentmode");
  492.     }
  493.     upmodes((BUFFER *) NULL);
  494.     return TRUE;
  495. }    
  496.  
  497. /*ARGSUSED*/
  498. fillmode(f, n, k) {
  499.  
  500.     if (f == FALSE) {
  501.         mode |= MFILL;
  502.         if ((binding[' '] = symlookup("insert-with-wrap")) == NULL)
  503.             panic("no insert-with-wrap in fillmode");
  504.     } else {
  505.         mode &= ~MFILL;
  506.         if ((binding[' '] = symlookup("self-insert-command")) == NULL)
  507.             panic("no self-insert-command in fillmode");
  508.     }
  509.     upmodes((BUFFER *) NULL);
  510.     return TRUE;
  511. }
  512.